import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class AdmonColaVS 
{
	public static ArrayList<InfoCamaraSubscrita> camarasSubscritasAServicio;
	
	/**
	 * @param args	Argumentos de llamada de consola
	 * 				[0]: Puerto de escucha de peticiones de inscripcion de camaras
	 * 				[1]: Puerto de escucha de peticiones de inicio de transmision VideoStreaming
	 */
	public static void main(String[] args) 
	{
		if(args.length != 2)
		{
			System.out.println("Debe usarlo con estos parametros: \n [0]: Puerto de escucha de peticiones de inscripcion de camaras \n [1]: Puerto de escucha de peticiones de inicio de transmision VideoStreaming");
			System.exit(-1);
		}
		
		AdmonColaVS.camarasSubscritasAServicio = new ArrayList<InfoCamaraSubscrita>();
		
		try
		{
			int puertoEscuchaPeticionesInscripcionCamaras = Integer.parseInt(args[0]);
			int puertoEscuchaPeticionesInicioTransmisionVS = Integer.parseInt(args[1]);
			
			// Inicia el servicio de escucha de peticiones de los monitores de transferencia de VS
			new HiloServicioTransferirPeticionesVS(puertoEscuchaPeticionesInicioTransmisionVS).start();
			
			// Inicia el servicio de escucha de inscripciones de camaras 
			ServerSocket servicioInscripcionCamaras = new ServerSocket(puertoEscuchaPeticionesInscripcionCamaras);
			System.out.println("Esperando a que se inscriba una camara");
			while(true)
			{
				new HiloWorkerInscripcionCamara(servicioInscripcionCamaras.accept()).start();
			}
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}

}

class InfoCamaraSubscrita
{
	public String ipCasa;
	public int puertoCasaEscuchaPeticionVS;
	public String codigoCasa;
	public String codigoCamara;
}

class HiloServicioTransferirPeticionesVS extends Thread
{
	private int puertoEscucha;
	
	public HiloServicioTransferirPeticionesVS(int puerto)
	{
		this.puertoEscucha = puerto;
	}
	
	public void run()
	{
		try
		{
			ServerSocket servicio = new ServerSocket(this.puertoEscucha);
			
			while(true)
			{
				new HiloWorkerTransferirPeticionesVS(servicio.accept()).start();
			}
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}
}

class HiloWorkerTransferirPeticionesVS extends Thread
{
	private Socket socketCliente;
	
	public HiloWorkerTransferirPeticionesVS(Socket cliente)
	{
		this.socketCliente = cliente;
	}
	
	public void run()
	{
		try
		{
			BufferedReader lectorCliente = new BufferedReader(new InputStreamReader(this.socketCliente.getInputStream()));
			String mensaje = lectorCliente.readLine();
			lectorCliente.close();
			this.socketCliente.close();
			
			if(mensaje != null && mensaje.length() > 13)
			{
				String puertoEscuchaMobile = mensaje.substring(0, 5);
				String codigoCasa = mensaje.substring(5, 9);
				String codigoCamara = mensaje.substring(9, 13);
				String ipMobile = mensaje.substring(13, mensaje.length());
				
				System.out.println("[Cola] Ha llegado la peticion de inicio de VS para la camara: " + codigoCamara);
				
				String mensajePeticion = String.format("%s%s%s", puertoEscuchaMobile, codigoCamara, ipMobile);
				
				System.out.println("[Cola] Num de camaras inscritas: " + AdmonColaVS.camarasSubscritasAServicio.size());
				
				for(InfoCamaraSubscrita camara: AdmonColaVS.camarasSubscritasAServicio)
				{
					if(camara.codigoCasa.equals(codigoCasa) && camara.codigoCamara.equals(codigoCamara))
					{
						System.out.println("[Cola] Se enviara solicitud a casa: " + mensajePeticion);
						
						Socket socketCasa = new Socket(camara.ipCasa, camara.puertoCasaEscuchaPeticionVS);
						PrintWriter escritura = new PrintWriter(socketCasa.getOutputStream(), true);
						escritura.println(mensajePeticion);
						escritura.close();
						socketCasa.close();
						
						break;
					}
					else
						System.out.println("[Cola] Esta no es la casa, se seguira con la siguiente. " + camara.codigoCasa + "_" + camara.codigoCamara);
				}
			}
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}
}


class HiloWorkerInscripcionCamara extends Thread
{
	private Socket socketCliente;
	
	public HiloWorkerInscripcionCamara(Socket cliente)
	{
		this.socketCliente = cliente;
	}
	
	public void run()
	{
		try
		{
			BufferedReader lectorCliente = new BufferedReader(new InputStreamReader(this.socketCliente.getInputStream()));
			
			String mensaje = lectorCliente.readLine();
			
			String ipCasa = socketCliente.getRemoteSocketAddress().toString().split(":")[0];
			ipCasa = ipCasa.substring(1, ipCasa.length());
			
			lectorCliente.close();
			this.socketCliente.close();
			
			if(mensaje != null && mensaje.length() == 13)
			{
				InfoCamaraSubscrita subscripcion = new InfoCamaraSubscrita();
				subscripcion.ipCasa = ipCasa;
				subscripcion.puertoCasaEscuchaPeticionVS = Integer.parseInt(mensaje.substring(0, 5).trim());
				subscripcion.codigoCasa = mensaje.substring(5, 9);
				subscripcion.codigoCamara = mensaje.substring(9, 13);
				
				synchronized(this)
				{
					AdmonColaVS.camarasSubscritasAServicio.add(subscripcion);
				}
				
				System.out.println("Se inscribio la camara: " + subscripcion.codigoCamara);
			}
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}
}

